package com.mm.learn.designpatterns.singleton;

/**
 * @author wdx
 * @date 2021年03月31日 17:24
 * <p>
 * 懒汉式 双重检查锁 线程安全
 * 类加载不会导致该单实例对象被创建，而是首次使用该对象时才会创建
 * 双重检查锁模式是一种非常好的单例实现模式，解决了单例、性能、线程安全问题，上面的双重检测锁模式看上去完美无缺，
 * 其实是存在问题，在多线程的情况下，可能会出现空指针问题，出现问题的原因是JVM在实例化对象的时候会进行优化和指令重排序操作。
 * 要解决双重检查锁模式带来空指针异常的问题，只需要使用 volatile 关键字, volatile 关键字可以保证可见性和有序性。
 */
public class Singleton4 {

    //私有构造方法
    private Singleton4() {
    }

    //在成员位置创建该类的对象
    private static volatile Singleton4 instance;

    //对外提供静态方法获取该对象
    public static  Singleton4 getInstance() {
        //第一次判断，如果instance不为null，不进入抢锁阶段，直接返回实例
        if (instance == null) {
            synchronized (Singleton4.class){
                //抢到锁之后再次判断是否为null
                if (instance == null){
                    instance = new Singleton4();
                }
            }
        }
        return instance;
    }


    public static void main(String[] args) {
        Singleton4 singleton1 = getInstance();
        Singleton4 singleton2 = getInstance();
        System.out.println(singleton1 == singleton2);
    }

}
